#pragma once

#include <OIS/OIS.h>

class KeyboardDevice
{
public:
	typedef TLongBitSet<8>	KeyBit;

public:
						KeyboardDevice(EventChannel* channel);
	virtual				~KeyboardDevice();

	virtual	void		UpdateKeyboard(float dt);
	OIS::Keyboard*		GetKeyboard()							{ return m_Keyboard; }	

public:
	bool				IsModifier(OIS::Keyboard::Modifier modifier);
	bool				IsPressed(OIS::KeyCode code);
	bool				IsReleased(OIS::KeyCode code);
	bool				IsTriggered(OIS::KeyCode code);
	bool				IsRepeated(OIS::KeyCode code);
	
	bool				IsCapsLock()							{ return m_IsCapslock; }

private:
	bool				ReadRawInput(float dt);

private:
	OIS::Keyboard*		m_Keyboard;
	EventChannel*		m_InputChannel;

	KeyBit				m_Pressed;
	KeyBit				m_Released;
	KeyBit				m_Triggered;
	KeyBit				m_Repeated;

	BitSet				m_Modifier;

	float				m_RepeatTimer;
	bool				m_IsRepeat;

	bool				m_IsCapslock;
};

class MouseDevice
{
public:
	enum Buttons
	{
		MOUSE_LEFT			= 0x0001,
		MOUSE_RIGHT			= 0x0002,
		MOUSE_MIDDLE		= 0x0004,
	};

public:
						MouseDevice(EventChannel* channel);
	virtual				~MouseDevice();

	virtual void		UpdateMouse(float dt);
	OIS::Mouse*			GetMouse()								{ return m_Mouse; }

public:
	bool				IsPressed(OIS::MouseButtonID code);
	bool				IsReleased(OIS::MouseButtonID code);
	bool				IsTriggered(OIS::MouseButtonID code);
	bool				IsRepeated(OIS::MouseButtonID code);

private:
	bool				ReadRawInput(float dt, OIS::MouseState& state);
	Buttons				ConvertBitValue(OIS::MouseButtonID code);

private:
	OIS::Mouse*			m_Mouse;
	EventChannel*		m_InputChannel;
	
	BitSet				m_Pressed;
	BitSet				m_Released;
	BitSet				m_Triggered;
	BitSet				m_Repeated;

	float				m_RepeatTimer;
	bool				m_IsRepeat;
};

//////////////////////////////////////////////////////////////////////////

class InputKeyEvent : public Event
{
	DECLARE_EVENT(0);
public:
	InputKeyEvent()			{}

public:
	bool					IsPressed(OIS::KeyCode code);
	bool					IsReleased(OIS::KeyCode code);
	bool					IsTriggered(OIS::KeyCode code);
	bool					IsRepeated(OIS::KeyCode code);
	bool					IsModifier(OIS::Keyboard::Modifier modifier);
	bool					IsCapsLock();
};

class InputMouseEvent : public Event
{
	DECLARE_EVENT(0);
public:
	InputMouseEvent()		{}
	InputMouseEvent(OIS::Axis x, OIS::Axis y, OIS::Axis z):AX(x), AY(y), AZ(z) {}

public:
	bool					IsPressed(OIS::MouseButtonID code);
	bool					IsReleased(OIS::MouseButtonID code);
	bool					IsTriggered(OIS::MouseButtonID code);
	bool					IsRepeated(OIS::MouseButtonID code);

public:
	OIS::Axis				AX;
	OIS::Axis				AY;
	OIS::Axis				AZ;
};